from flask import Blueprint, send_file, jsonify, g
from flask_restful import reqparse, current_app, request
from application.models.users.user import User

user_blue = Blueprint("userblue", __name__)
from captcha.image import ImageCaptcha
import random, redis, json, jwt, time
from app import db
from ronglian_sms_sdk import SmsSDK


# 装饰器
def login(func):
    def warpper(*args, **kwargs):
        req = reqparse.RequestParser()
        req.add_argument("token", location="headers")
        args = req.parse_args()

        token = args["token"]
        key = current_app.config.get("SECRET_KEY")

        try:
            payload = jwt.decode(token, key, algorithms="HS256")  # 解码
            g.id = payload['id']  # 根据g传值user_id  这是用户id
        except:
            return jsonify({
                'code': 403,
                "msg": "用户未登录"
            })
        return func(*args, **kwargs)

    return warpper


@user_blue.route("/reg/<uuid>")
def reg(uuid):
    img = ImageCaptcha()
    code = str(random.randint(1000, 9999))
    img_png = img.generate(code)  # 调用验证码对象的generate方法， 生成图片，返回的图片为二进制数据

    rds = redis.Redis(port=6379, host='127.0.0.1')
    rds.set("code_%s" % uuid, code, ex=300)  # uuid相当于媒介 存放code
    rds.close()

    return send_file(img_png, mimetype='png')  # flask提供了返回二进制文件的方法 send——file（文件， 格式）


@user_blue.route("/mob/<uuid>", methods=["POST"])
def mob(uuid):
    man = request.json
    uuidpas = man.get("uuidpas")
    mobile = man.get("mobile")

    rds = redis.Redis(port=6379, host='127.0.0.1')
    uuid2 = rds.get("code_%s" % uuid)  # uuid相当于媒介 存放code
    rds.close()

    if uuid2.decode() != str(uuidpas):
        return jsonify({
            'code': 400,
            'msg': "图形验证码错误"
        })

    rds = redis.Redis(port=6379, host='127.0.0.1')
    try:
        send_flag = rds.get("sms_%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if send_flag is not None:
            # 表示60秒内有之前发送的记录
            return jsonify({
                'code': 400,
                'msg': "请求过于频繁，请60秒后重试！"
            })

    accid = "8aaf070881ad8ad401821a3f28951ba3"
    acctoken = "5f34081c4ff141c48ceea056ffd70226"
    appid = "8aaf070881ad8ad401821a3f296a1baa"
    tid = "1"
    sms_time = 5
    code = str(random.randint(100000, 999999))

    sdk = SmsSDK(accid, acctoken, appid)
    rs = sdk.sendMessage(tid, mobile, (code, sms_time))

    rds.set("sms_%s" % mobile, code, ex=60)  # uuid相当于媒介 存放code
    rds.close()

    re_data = json.loads(rs)
    if re_data["statusCode"] == "000000" or re_data["statusCode"] == "112310":
        return jsonify({
            "code": 200,
            "msg": "发送成功"
        })
    else:
        return jsonify({
            'code': 400,
            "msg": "发送失败"
        })


@user_blue.route("/login", methods=["POST"])
def login():
    man = request.json
    username = man.get("username")
    mobile = man.get("mobile")
    code = man.get("code")

    rds = redis.Redis(port=6379, host='127.0.0.1')
    mob = rds.get("sms_%s" % mobile)
    rds.close()

    if not mob!=None:
        return jsonify({
            'code': 200,
            "msg": "验证码错误"
        })

    if mob.decode() != str(code):
        return jsonify({
            'code': 400,
            'msg': "短信验证码错误"
        })

    user_info = User.query.filter(User.mobile == mobile).first()
    if not user_info:  # 判断是否重复
        us = User(nikename=username, mobile=mobile, password="123456")
        db.session.add(us)
        db.session.commit()
        return jsonify({
            'code': 200,
            'msg': "注册成功",
        })
    # 登录  token加密
    payload = {
        "id": user_info.id,
        'exp': int(time.time()) + 7200
    }

    key = current_app.config.get("SECRET_KEY")
    token = jwt.encode(payload, key, algorithm="HS256")

    if user_info:
        return jsonify({
            'code': 200,
            "msg": "登录成功",
            'data': {
                "token": token
            }
        })
